#include <string.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>

using namespace std;

//01 String深拷贝阶段
class String{
public:
    String()
        :_pstr(new char[1]()){

        }

    String(const char * pstr)
        :_pstr(new char[strlen(pstr)+1]()){
            strcpy(_pstr,pstr);
        }


    //拷贝构造
    String(const String &rhs)
        :_pstr(new char[strlen(rhs._pstr) + 1]())
    {
        cout << "String(const String &)" << endl;
        strcpy(_pstr, rhs._pstr);
    }

    //移动构造
    String(String &&rhs)
        :_pstr(rhs._pstr)
    {
        cout << "String(String &&)" << endl;
        rhs._pstr = nullptr;
    }

    //赋值运算符
    String &operator=(const String &rhs) {
        cout << "String & operator=(const String &)" << endl;
        if (this != &rhs) {
            delete[] _pstr;
            _pstr = new char[strlen(rhs._pstr) + 1]();
            strcpy(_pstr, rhs._pstr);
        }
        return *this;
    }

    //移动赋值
    String &operator=(String &&rhs) {
        cout << "String & operator=(String &&)" << endl;
        if (this != &rhs) {
            delete[] _pstr;
            _pstr = rhs._pstr;
            rhs._pstr = nullptr;
        }
        return *this;
    }


    ~String(){
        if(_pstr){
            delete [] _pstr;
            _pstr = nullptr;
        }
    }

    size_t size() const{
        return strlen(_pstr);
    }

    const char * c_str() const{
        return _pstr;
    }

    String & operator+=(const String & rhs){
        if(rhs.size() > 0){
            char * temp = new char[size()+rhs.size()+1]();
            strcpy(temp,_pstr);
            strcat(temp,rhs._pstr);
            delete [] _pstr;
            _pstr = temp;
        }
        return *this;
    }

    String & operator+=(const char * pstr){
        String temp(pstr);
        *this += temp;
        return *this;
    }

    char & operator[](size_t index){
        if(index >= size()){
            cerr << "index out of range" << endl;
            static char nullchar = '\0';
            return nullchar;
        }
        return _pstr[index];
    }

    //第一个const：防止被修改值
    //第二个const：用于const对象的调用，不加const对象无法调用
    const char & operator[](size_t index) const {
        if(index >= size()){
            cerr << "index out of range" << endl;
            static char nullchar = '\0';
            return nullchar;
        }
        return _pstr[index];
    }

    friend bool operator==(const String & lhs,const String & rhs);
    friend bool operator!=(const String & lhs,const String & rhs);
    friend bool operator>=(const String & lhs,const String & rhs);
    friend bool operator<=(const String & lhs,const String & rhs);
    friend bool operator>(const String & lhs,const String & rhs);
    friend bool operator<(const String & lhs,const String & rhs);

    friend ostream & operator<<(ostream & os,const String & rhs);
    friend istream & operator>>(istream & is,String & rhs);
private:
    char * _pstr;
};

bool operator==(const String & lhs,const String & rhs){
    return strcmp(lhs._pstr,rhs._pstr)==0;
}

bool operator!= (const String & lhs,const String & rhs){
    return strcmp(lhs._pstr,rhs._pstr)!=0;
}

bool operator>= (const String & lhs,const String & rhs){
    return strcmp(lhs._pstr,rhs._pstr)>=0;
}

bool operator<= (const String & lhs,const String & rhs){
    return strcmp(lhs._pstr,rhs._pstr)<=0;
}

bool operator> (const String & lhs,const String & rhs){
    return strcmp(lhs._pstr,rhs._pstr)>0;
}

bool operator< (const String & lhs,const String & rhs){
    return strcmp(lhs._pstr,rhs._pstr)<0;
}

ostream & operator<<(ostream & os,const String & rhs){
    os << rhs._pstr;
    return os;
}

istream & operator>>(istream & is,String & rhs){
    char ch;
    vector<char> vec;
    while((ch = is.get()) != '\n'){
        vec.push_back(ch);
    }

    delete  [] rhs._pstr;
    rhs._pstr = new char[vec.size()+1];
    for(int i = 0; i < vec.size(); ++i){
        rhs. _pstr[i] = vec[i];
    }
    return is;
}

//operator+不需要（不适合）在类内声明的原因是：
//成员函数无法支持左操作数为非类对象的场景；
//全局函数能灵活处理不同类型的操作数组合，覆盖所有可能的拼接场景。

//全局函数实现+既满足对称性，又支持多种类型组合
String operator+(const String & lhs,const String & rhs){
    String temp(lhs);
    temp += rhs;
    return temp;
}

String operator+(const String & lhs,const char * pstr){
    String temp(lhs);
    temp += pstr;
    return temp;
}


String operator+(const char * pstr,const String & rhs){
    String temp(pstr);
    temp += rhs;
    return temp;
}

void test() {
    //拷贝构造
    //String s1("hello");
    //String s2(s1);

    //赋值运算符
    /* String s3("cpp"); */
    /* String s4("java"); */
    /* cout << s3 << ":" << s4 << endl; */
    /* s3 = s4; */
    /* cout << s3 << ":" << s4 << endl; */
}

String creatString(const char *str) {
    String temp(str);
    return temp;
}

//移动构造
void test2() {
    //String s1 = String("world");

    //cout << creatString("hello") << endl;

    String s2("hello");
    String s3 = move(s2);

}

//移动赋值
void test3() {
    //String s1("hello");
    //s1 = String("python");

    String s2("hello");
    String s3("world");
    cout << s2 << ":" << s3 << endl;
    s3 = move(s2);
    cout << s2 << ":" << s3 << endl;
}

//+=,size,c_str()
void test4() {
    String s1("hello ");
    cout << s1.size() << endl;
    s1.c_str();
    cout << s1 << endl;
    //String s2("world");
    //s1 += s2;

    const char *pstr = "cpp";
    s1 += pstr;
    cout << s1 << endl;
}

//>>
void test5() {
    String s;
    cin >> s;
    cout << s << endl;
}

//== != >= <= > <
void test6() {
    String s1("hello");
    String s2("hello");
    String s3("world");
    cout << (s1 == s2) << endl;
    cout << (s1 != s3) << endl;

    cout << (s1 >= s3) << endl;
    cout << (s1 > s2) << endl;
    cout << (s1 <= s3) << endl;
    cout << (s1 < s3) << endl;
}

//[]
void test7() {
    String s1("hello");
    cout << s1[0] << endl;
    cout << s1[8] << endl;
    s1[0] = 'H';
    cout << s1 << endl;

    const String s2("world");
    cout << s2[1] << endl;
    //s2[0]= 'W'; error
}

//+
void test8() {
    String s1("hello ");
    //String s2("world");
    //String s3 = s1 + s2;

    const char *pstr = "cpp";
    //String s3 = s1 + pstr;
    String s3 = pstr + s1;
    cout << s3 << endl;
}




int main()
{
    test8();
    return 0;
}

